package com.file.system.controller.system;


import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.file.system.entity.basic.WebCurrent;
import com.file.system.entity.dict.IsSuperAdmin;
import com.file.system.entity.res.BaseCode;
import com.file.system.entity.res.CommonResult;
import com.file.system.entity.system.WebMenu;
import com.file.system.entity.system.WebUser;
import com.file.system.plugin.shiro.ShiroTools;
import com.file.system.plugin.validated.SQLInjectionValidation;
import com.file.system.service.system.IWebMenuService;
import com.file.system.service.system.IWebRoleMenuService;
import com.file.system.service.system.IWebUserService;
import com.file.system.service.system.ShiroService;
import com.file.system.tools.rand.RandCheckCode;
import com.file.system.tools.regular.RegularUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import java.util.List;

import static cn.hutool.core.util.ObjectUtil.equal;
import static cn.hutool.crypto.digest.DigestUtil.md5Hex;


/**
 * shiro用户登录
 *
 * @author 靳春晖
 */
@RestController
@RequestMapping(value = "/")
@Validated
public class LoginController {

    @Autowired
    private IWebUserService iWebUserService;
    // 注入shiro服务
    @Autowired
    private ShiroService shiroService;
    // 注入角色菜单服务
    @Autowired
    private IWebRoleMenuService iWebRoleMenuService;
    // 注入菜单服务
    @Autowired
    private IWebMenuService iWebMenuService;
    // 注入随机验证码
    @Autowired
    private RandCheckCode randCheckCode;


    /**
     * 用户登录
     *
     * @param username 用户名|admin
     * @param password 密码|c4ca4238a0b923820dcc509a6f75849b
     * @return CommonResult
     * @apiNote 通过用户名、密码、验证码进行登录
     * @author 靳春晖
     * @since login
     */
    @PostMapping("login/{username}/{password}")
    public CommonResult<WebUser> loginPOST(
            @PathVariable
            @NotEmpty(message = "用户名不能为空")
            @Size(min = 5, max = 20, message = "用户名长度为5-20")
            @SQLInjectionValidation(fieldName = "用户名")
            String username,
            @PathVariable
            @NotEmpty(message = "密码不能为空")
            @Size(min = 32, max = 32, message = "密码长度为32")
            @SQLInjectionValidation(fieldName = "密码")
            String password
    ) {
        //获取验证码
        /*String randCheckCode = (String) ShiroTools.getSession().getAttribute("randCheckCode");
        if (StrUtil.isEmpty(randCheckCode)) {
            return CommonResult.fail(BaseCode.Common.PARAM_CODE_CREATE_ERROR);
        }
        //验证码是否匹配
        if (!code.equalsIgnoreCase(randCheckCode)) {
            return CommonResult.fail(BaseCode.Common.PARAM_CODE_ERROR);
        }*/
        //查询用户是否存在
        QueryWrapper<WebUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.and(l -> l.eq("a.username", username).or()
                        .eq("a.email", username).or()
                        .eq("a.phone", username))
                .eq("a.is_del", "0");

        List<WebUser> list = iWebUserService.list(queryWrapper);
        if (list.isEmpty()) {
            return CommonResult.fail(BaseCode.Common.USER_PASSWORD_ERROR);
        }
        if (list.size() > 1) {
            return CommonResult.fail(BaseCode.Common.USER_NOT_ONE_ERROR);
        }
        //登录用户名
        WebUser loginUser = list.get(0);
        //shiro登录
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(loginUser.getUsername(), md5Hex(password));
        try {
            subject.login(token);
            WebUser user = (WebUser) subject.getPrincipal();
            return CommonResult.ok().setResult(user);
        } catch (Exception e) {
            //登录报错返回
            return CommonResult.fail().setText(e.getMessage());
        }
    }


    /**
     * 登录验证码
     *
     * @param request
     * @param response
     * @return void
     * @apiNote 获取登录验证码
     * @author 靳春晖
     */
    @PostMapping("login/code")
    public void code(HttpServletRequest request, HttpServletResponse response) {
        randCheckCode.buildCheckCode(request, response);
    }

    /**
     * 退出登录
     *
     * @param request
     * @param response
     * @return void
     * @apiNote -
     * @author 靳春晖
     */
    @PostMapping("login/out")
    public CommonResult logout(HttpServletRequest request, HttpServletResponse response) {
        WebUser user = ShiroTools.getShiroUser();
        if (user != null) {
            Subject subject = SecurityUtils.getSubject();
            subject.logout();
        }
        return CommonResult.ok();
    }


    /**
     * 获取当前用户信息
     *
     * @apiNote 获取登录验证码
     * @author 靳春晖
     */
    @PostMapping("current")
    public CommonResult<WebCurrent> current() {
        WebCurrent webCurrent = new WebCurrent();
        webCurrent.setWebUser(ShiroTools.getShiroUser());

        List<WebMenu> menuList;
        WebUser user = ShiroTools.getShiroUser();
        if (user == null) {
            return CommonResult.fail();
        }
        //判断是否为超级管理员
        if (equal(user.getIsSuperAdmin(), IsSuperAdmin.YES.val)) {
            //获取菜单列表
            menuList = iWebMenuService.list(new QueryWrapper<WebMenu>()
                    .eq("a.is_del", 0)
                    .orderByAsc("a.sort")
            );
        } else {
            //获取用户权限
            menuList = shiroService.getUserAuth(ShiroTools.getId());
        }
        webCurrent.setMenuList(menuList);
        return CommonResult.ok().setResult(webCurrent);
    }

}